﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using My.Admin.Dynamic;
using My.Admin.Service.System;
using My.Admin.Service.System.IService;
using My.Core.Constant;
using My.Core.DynamicProxy;
using My.Core.Enums;
using My.Core.Extensions;
using My.Core.Options;
using My.Core.Util;
using My.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace My.Core.Authorization.Handler
{
    public class JwtHandler : IAuthorizationHandler, ISingletonAutoInject
	{
        /// <summary>
        /// 自动刷新Token
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task HandleAsync(AuthorizationHandlerContext context)
        {
            // 获取Token过期时间
            //var serviceProvider = context.GetCurrentHttpContext().RequestServices;
            JwtSettings jwtSettings = new();
            AppSettings.Bind("JwtSettings", jwtSettings);

            if (JWTEncryption.AutoRefreshToken(context, context.GetCurrentHttpContext(), jwtSettings.Expire, jwtSettings.RefreshTokenTime))
            {
				await AuthorizeHandleAsync(context);
			}
            else
            {
                context.Fail(); // 授权失败
                DefaultHttpContext currentHttpContext = context.GetCurrentHttpContext();
                if (currentHttpContext == null)
                    return;
                currentHttpContext.SignoutToSwagger();
            }
        }

		public async Task<bool> PipelineAsync(AuthorizationHandlerContext context, DefaultHttpContext httpContext)
		{
			// 已自动验证 Jwt Token 有效性
			return await CheckAuthorizeAsync(httpContext);
		}

		/// <summary>
		/// 策略验证管道
		/// </summary>
		/// <param name="context"></param>
		/// <param name="httpContext"></param>
		/// <param name="requirement"></param>
		/// <returns></returns>
		public async Task<bool> PolicyPipelineAsync(AuthorizationHandlerContext context, DefaultHttpContext httpContext, IAuthorizationRequirement requirement)
		{
			return await Task.FromResult(true);
		}

		/// <summary>
		/// 权限校验核心逻辑
		/// </summary>
		/// <param name="httpContext"></param>
		/// <returns></returns>
		private static async Task<bool> CheckAuthorizeAsync(DefaultHttpContext httpContext)
		{
			var user = App.User;

			// 排除超管
			if (App.User.FindFirst(ClaimConst.AccountType)?.Value == ((int)AccountTypeEnum.SuperAdmin).ToString())
				return true;

			// 路由名称
			var routeName = httpContext.Request.Path.StartsWithSegments("/api")
				? httpContext.Request.Path.Value[5..].Replace("/", ":")
				: httpContext.Request.Path.Value[1..].Replace("/", ":");

			// 获取用户拥有按钮权限集合
			var sysMenuService = App.ServiceProvider.GetService<ISysMenuService>();
			var ownBtnPermList = await sysMenuService.GetOwnBtnPermList();
			// 获取系统所有按钮权限集合
			var allBtnPermList = await sysMenuService.GetAllBtnPermList();

			// 已拥有该按钮权限或者所有按钮集合里面不存在
			var exist1 = ownBtnPermList.Exists(u => routeName.Equals(u, System.StringComparison.CurrentCultureIgnoreCase));
			var exist2 = allBtnPermList.TrueForAll(u => !routeName.Equals(u, System.StringComparison.CurrentCultureIgnoreCase));
			return exist1 || exist2;
		}

		/// <summary>
		/// 授权处理
		/// </summary>
		/// <param name="context"></param>
		/// <returns></returns>
		protected async Task AuthorizeHandleAsync(AuthorizationHandlerContext context)
		{
			// 获取所有未成功验证的需求
			var pendingRequirements = context.PendingRequirements;

			// 获取 HttpContext 上下文
			var httpContext = context.GetCurrentHttpContext();

			// 调用子类管道
			var pipeline = await PipelineAsync(context, httpContext);
			if (pipeline)
			{
				// 通过授权验证
				foreach (var requirement in pendingRequirements)
				{
					// 验证策略管道
					var policyPipeline = await PolicyPipelineAsync(context, httpContext, requirement);
					if (policyPipeline) context.Succeed(requirement);
					else context.Fail();
				}
			}
			else context.Fail();
		}
	}
}
